package jp.co.tms.internal.runserver;

import java.io.IOException;
import java.net.BindException;
import java.util.HashMap;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import jp.co.tms.internal.data.ITaskQueue;
import jp.co.tms.internal.runserver.exception.ConnectionIsInUseException;
import jp.co.tms.internal.runserver.exception.ConnectionIsOutException;
import jp.co.tms.internal.runserver.exception.NoHandleException;
import jp.co.tms.internal.runserver.exception.PortNumberIsUnLegalException;
import jp.co.tms.internal.task.IKillTask;
import jp.co.tms.internal.task.IRunTask;
import jp.co.tms.internal.task.ITask;

public class RunServerManager extends TimerTask implements IRunServerEventHandle {
	// 1 second (standard time)
	public final static int DEF_SECOND        = 1000;
	// 4 seconds(initialize time)
	public final static int DEF_DELAY_TIME    = 4 * DEF_SECOND;
	// 1 second (task flush interval time)
	public final static int DEF_INTERVAL_TIME = 1 * DEF_SECOND;
	// timer engine.
	private Timer _timer = new Timer();
	// server control.
	private RunServerCtrl _core = new RunServerCtrl(this);
	// task map.
	private Map<Integer, ITask> _runningTasks = new HashMap<Integer, ITask>();
	// input queue.
	private ITaskQueue _inputQueue;
	// out put queue.
	private ITaskQueue _outputQueue;
	
	public RunServerManager(ITaskQueue input, ITaskQueue output){
		this._inputQueue  = input;
		this._outputQueue = output;
	}
	
	public boolean start(){
		try{
			//
			// Start the socket connection.
			_core.run();
			//
			// Start the timer.
			_timer.schedule(this, 
					DEF_DELAY_TIME,
					DEF_INTERVAL_TIME);
			//
			// success.
			return true;
		}
		catch (NoHandleException e){
			System.out.println("ERROR: No Event handle.");
		}
		catch (ConnectionIsInUseException e){
			System.out.println("ERROR: The Connection is in use.");
		}
		catch (PortNumberIsUnLegalException e){
			System.out.println("ERROR: Port Number is not legal.");
		}
		catch (ConnectionIsOutException e){
			System.out.println("ERROR: The Connection is out.");
		}
		catch (BindException e){
			System.out.println("ERROR: The port is already in use.");
		}
		catch (IOException e){
			System.out.println("ERROR: IO Exception.");
		}
		
		return false;
	}
	
	public void stop(){
		//
		// Stop the timer.
		_timer.cancel();
	}
	
	public boolean hasIdleCpu(){
		return _core.hasIdleCpu();
	}
	
	public synchronized boolean onTaskRunning(int taskId) {
		ITask task = _runningTasks.get( taskId );
		if (task == null){
			return false;
		}
	
		return true;
	}
	
	public synchronized boolean onTaskFinish(int taskId) {
		ITask task = _runningTasks.get( taskId );
		if (task == null){
			return false;
		}
		
		if (_outputQueue.offer(task))
			_runningTasks.remove(task);
		else
			return false;
		
		return true;
	}

	public synchronized boolean onTaskKilled(int taskId) {
		return true;
	}
	
	public void run() {
		//
		// if the socket is not idle return.
		if ( !_core.hasIdleCpu() ){
			return;
		}
		//
		// throw a task to run server.
		throwTaskToSocket();
	}
	
	private synchronized void throwTaskToSocket(){
		ITask task = _inputQueue.poll();
		if ( task == null )
			return;
		
		_runningTasks.put(task.getId(), task);
		
		if (task instanceof IRunTask ){
			_core.startTask((IRunTask)task) ;
		}
		else if ( task instanceof IKillTask ){
			/* No have kill command */
		}
		else{
			//TO Nothing;
		}
	}
}
